#include "../include/lexanalyze.h"  

//常数判断
int isNumber(void *self, const char *s, int lineNo, int colNo)
{
    int hasDot = 0, hasE = 0; // 标志变量，用于跟踪小数点和e/E
    int dotPosition = -1;     // 小数点位置
    int ePosition = -1;       // e/E 字符位置
    const char *x = s;
    // 跳过可能的空白字符
    while (*s == ' ')
    {
        s++;
        colNo++;
    }

    // 处理正负号
    if (*s == '+' || *s == '-')
    {
        s++;
        colNo++; // 更新列号
    }

    // 处理数字部分
    while (*s)
    {
        if (isdigit(*s))
        {
            s++;
            colNo++;
        }
        else if (*s == '.' && !hasDot && !hasE)
        {
            hasDot = 1;          // 只允许一个小数点
            dotPosition = colNo; // 记录小数点位置
            s++;
            colNo++;
        }
        else if ((*s == 'e' || *s == 'E') && !hasE)
        {
            hasE = 1;          // 只允许一个 'e' 或 'E'
            ePosition = colNo; // 记录e/E位置
            s++;
            colNo++;

            // 处理指数部分的正负号
            if (*s == '+' || *s == '-')
            {
                s++;
                colNo++;
            }
            while (isdigit(*s))
            {
                s++;
                colNo++;
            }
        }
        else
        {
            printf("\033[31merror: '%s' Not a constant, line %d, column %d.\033[0m", x, lineNo, colNo);
            return 0; // 遇到非法字符
        }
    }

    return 1; // 有效的数字
}

// 处理标识符表函数
int symbol(void *self, char *word, int lineNo, int colNo)
{
    LexAnalyze *lexAnalyze = (LexAnalyze *)self;
    // 检查首字符是否为字母或下划线
    if (word[0] != '_' && !isalpha(word[0]))
    {
        printf("\033[31merror: '%s' Illegal naming, line %d, column %d.\033[0m", word, lineNo, colNo);
        return 0;
    }

    // 检查后续字符是否为字母、数字或下划线
    for (int i = 1; word[i] != '\0'; i++)
    {
        if (word[i] != '_' && !isalnum(word[i]))
        {
            printf("\033[31merror: '%s' Illegal naming, line %d, column %d.\033[0m", word, lineNo, colNo);
            return 0;
        }
    }
    printf("('%s',202)\n", word);
    sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "202 ");
    return 3;
}

//标识符判断
int letter(void *self)
{
    LexAnalyze *lexAnalyze = (LexAnalyze *)self;
    if ((lexAnalyze->token[lexAnalyze->i] >= 'A' && lexAnalyze->token[lexAnalyze->i] <= 'Z') || (lexAnalyze->token[lexAnalyze->i] >= 'a' && lexAnalyze->token[lexAnalyze->i] <= 'z') || lexAnalyze->token[lexAnalyze->i] == '_')
    {
        return 1;
    }
    return 0;
}

// 判断数字的函数
int digit(void *self)
{
    LexAnalyze *lexAnalyze = (LexAnalyze *)self;
    static int f1 = 0, f2 = 0;
    if (f1 && !f2)
    {
        if (lexAnalyze->token[lexAnalyze->i] == '+' || lexAnalyze->token[lexAnalyze->i] == '-' || (lexAnalyze->token[lexAnalyze->i] >= '0' && lexAnalyze->token[lexAnalyze->i] <= '9'))
        {
            f2 = 1;
            return 1;
        }
    }
    if (lexAnalyze->token[lexAnalyze->i] >= '0' && lexAnalyze->token[lexAnalyze->i] <= '9')
    {
        return 1;
    }
    if (lexAnalyze->token[lexAnalyze->i] == '.' || lexAnalyze->token[lexAnalyze->i] == 'e')
    {
        if (lexAnalyze->token[lexAnalyze->i] == 'e')
            f1 = 1;
        return 1;
    }
    f1 = f2 = 0;
    return 0;
}

// 处理保留字表函数
int reserve(void *self, int lineNo, int colNo)
{
    LexAnalyze *lexAnalyze = (LexAnalyze *)self;
    char word[10];
    char protect[100][100] = {
        "auto",           // 自动变量
        "break",          // 跳脱
        "case",           // 情况标签
        "char",           // 字符类型
        "const",          // 常量
        "continue",       // 继续
        "default",        // 默认情况
        "do",             // 循环
        "double",         // 双精度浮点
        "else",           // 否则
        "enum",           // 枚举
        "extern",         // 外部链接
        "float",          // 单精度浮点
        "for",            // 循环
        "goto",           // 转到
        "if",             // 条件语句
        "int",            // 整数类型
        "long",           // 长整数
        "register",       // 寄存器存储类
        "return",         // 返回
        "short",          // 短整数
        "signed",         // 有符号类型
        "sizeof",         // 大小操作符
        "static",         // 静态存储持续时间和内部链接
        "struct",         // 结构体
        "switch",         // 开关语句
        "typedef",        // 类型定义
        "union",          // 联合体
        "unsigned",       // 无符号类型
        "void",           // 无类型
        "volatile",       // 不稳定类型
        "while",          // 循环
        "_Bool",          // 布尔类型（C99）
        "_Complex",       // 复数类型（C99）
        "_Imaginary",     // 虚数类型（C99）
        "_Atomic",        // 原子操作（C11）
        "_Generic",       // 通用表达式（C11）
        "_Noreturn",      // 不返回函数（C11）
        "_Static_assert", // 静态断言（C11）
        "_Thread_local"   // 线程本地存储（C11）
    };
    int n = 0;
    word[n++] = lexAnalyze->token[lexAnalyze->i++];
    while (letter(self) || digit(self)) // 判断当前字符是字母还是数字
    {
        word[n++] = lexAnalyze->token[lexAnalyze->i++];
    }
    word[n] = '\0';
    lexAnalyze->i--;
    // 判断是否为保留字
    for (n = 0; n < 100; n++)
    {
        if (strcmp(word, protect[n]) == 0)
        {
            printf("('%s',1)\n", protect[n]);
            sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "1 ");
            return 3;
        }
    }
    return symbol(self, word, lineNo, colNo);
}

// 词法分析
int toLexAnalyze(void *self)
{
    LexAnalyze *lexAnalyze = (LexAnalyze *)self;
    char* current = lexAnalyze->pData;
    static int lineNo = 1; // 行号
    static int colNo = 0;  // 列号
    if (lexAnalyze->is_f_j == 1)
    {
        char word[10];
        int n = 0;
        word[n++] = lexAnalyze->token[lexAnalyze->i++];
        while (lexAnalyze->token[lexAnalyze->i] != '\\' && lexAnalyze->token[lexAnalyze->i] != '\'' && lexAnalyze->token[lexAnalyze->i] != '\"') // 判断当前字符是字母还是数字
        {
            word[n++] = lexAnalyze->token[lexAnalyze->i++];
        }
        word[n] = '\0';
        lexAnalyze->is_f_j = 2;
        lexAnalyze->i--;
        printf("('%s',201)\n", word);
        
        sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "201 ");
        return 3;
    }
    else if (letter(self)) // 标识符
    {
        return reserve(self, lineNo, colNo);
    }
    else if (digit(self))
    {
        char x[100];
        int n = 0;
        x[n++] = lexAnalyze->token[lexAnalyze->i++];

        while (digit(self))
        {
            x[n++] = lexAnalyze->token[lexAnalyze->i++];
        }
        x[n] = '\0';
        lexAnalyze->i--;
        if (isNumber(self, x, lineNo, colNo))
        {
            printf("('%s',3)\n", x);
            sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "3 ");
            return 3;
        }
    }
    else // 判断其他各种字符
        switch (lexAnalyze->token[lexAnalyze->i])
        {
        case ' ':
        case '\n':
            if (lexAnalyze->token[lexAnalyze->i] == '\n')
            {
                lineNo++;  // 行号增加
                colNo = 0; // 列号重置
            }
            colNo++;
            return -1;
        case '#':
            return 0;
        case '=':
            printf("('=',401)\n");
            sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "401 ");
            return 3;
        case '<':
            lexAnalyze->i++;
            if (lexAnalyze->token[lexAnalyze->i] == '=')
            {
                printf("('<=',402)\n");
                sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "402 ");
                return 3;
            }
            else if (lexAnalyze->token[lexAnalyze->i] == '<')
            {
                printf("('<<',403)\n");
                sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "403 ");
                return 3;
            }
            else
            {
                lexAnalyze->i--;
                printf("('<',404)\n");
                sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "404 ");
                return 3;
            }
        case '>':
            lexAnalyze->i++;
            if (lexAnalyze->token[lexAnalyze->i] == '=')
            {
                printf("('>=',405)\n");
                sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "405 ");
                return 3;
            }else if(lexAnalyze->token[lexAnalyze->i] == '>'){
                printf("('>>',406)\n");
                sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "406 ");
            }
            else
            {
                lexAnalyze->i--;
                printf("('>',407)\n");
                sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "407 ");
                return 3;
            }
        case '+':
            lexAnalyze->i++;
            if (lexAnalyze->token[lexAnalyze->i] == '=')
            {
                printf("('+=',408)\n");
                sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "408 ");
                return 3;
            }
            else if (lexAnalyze->token[lexAnalyze->i] == '+')
            {
                printf("('++',409)\n");
                sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "409 ");
                return 3;
            }
            else
            {
                lexAnalyze->i--;
                printf("('+',410)\n");
                sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "410 ");
                return 3;
            }
        case '-':
            lexAnalyze->i++;
            if (lexAnalyze->token[lexAnalyze->i] == '='){
                printf("('-=',411)\n");
                sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "411 ");
            }else if(lexAnalyze->token[lexAnalyze->i] == '-'){
                printf("('--',412)\n");
                sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "412 ");
            }else{
                lexAnalyze->i--;
                printf("('-',413)\n");
                sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "413 ");
            }
            return 3;
        case '*':
            lexAnalyze->i++;
            if (lexAnalyze->token[lexAnalyze->i] == '='){
                printf("('*=',414)\n");
                sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "414 ");
            }else{
                lexAnalyze->i--;
                printf("('*',415)\n");
                sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "415 ");
            }
            return 3;
        case '/':
            lexAnalyze->i--;
            printf("('/',416)\n");
            sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "416 ");
            return 3;
        case ':':
            printf("(':',501)\n");
            sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "501 ");
            return 3;
        case ';':
            printf("(';',502)\n");
            sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "502 ");
            return 3;
        case '(':
            printf("('(',417)\n");
            sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "417 ");
            return 3;
        case ')':
            printf("(')',418)\n");
            sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "418 ");
            return 3;
        case '{':
            printf("('{',503)\n");
            sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "503 ");
            return 3;
        case '}':
            printf("('}',504)\n");
            sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "504 ");
            return 3;
        case '[':
            printf("('[',419)\n");
            sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "419 ");
            return 3;
        case ']':
            printf("(']',420)\n");
            sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "420 ");
            return 3;
        case '|':
            printf("('|',421)\n");
            sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "421 ");
            return 3;
        case '"':
            if (lexAnalyze->is_f_j)
                lexAnalyze->is_f_j = 0;
            else if (!lexAnalyze->is_f_j)
                lexAnalyze->is_f_j = 1;
            printf("('\"',505)\n");
            sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "505 ");
            return 3;
        case ',':
            printf("(',',506)\n");
            sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "506 ");
            return 3;
        case '\'':
            if (lexAnalyze->is_f_j)
                lexAnalyze->is_f_j = 0;
            else if (!lexAnalyze->is_f_j)
                lexAnalyze->is_f_j = 1;
            printf("('\'',507)\n");
            sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "507 ");
            return 3; // 单引号
        case '&':
            lexAnalyze->i++;
            if (lexAnalyze->token[lexAnalyze->i] != '&')
            {
                lexAnalyze->i--;
                printf("('&',422)\n");
                sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "422 ");
                return 3;
            }
            else
            {
                printf("('&&',423)\n");
                sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "423 ");
                return 3;
            }
        case '\\':
            printf("('\\',424)\n");
            sprintf(lexAnalyze->pData + strlen(lexAnalyze->pData), "424 ");
            printf("%s",lexAnalyze->pData);
            return 3;
        default:
            printf("Lexical analysis has ended!\n");
            return 0; // 错误判断
        }
    return 0;
}

void getLexAnalyze(void *self){
    LexAnalyze *lexAnalyze = (LexAnalyze *)self;
    int m;
    do
    {
        m = lexAnalyze->toLexAnalyze(lexAnalyze);
        switch (m)
        {
        case -1:lexAnalyze->i++; break;
        case 0: lexAnalyze->i++; break;
        case 3: lexAnalyze->i++; break;
        }
    } while (m != 0);
    writer(lexAnalyze->pData,strlen(lexAnalyze->pData)*sizeof(char),"C:\\Users\\18098\\Desktop\\zdw-gcc\\lexanalyze\\shared_memory.dat");
}

//初始化
LexAnalyze* LexAnalyze_creat(const char *filepath){
    LexAnalyze* p = (LexAnalyze*)malloc(sizeof(LexAnalyze));  
    if (p) {  
        int c = 0;
        char token[250];
        FILE *fp;
        fp=fopen(filepath,"r");//"D:\\test.c"
        if (fp == NULL)
        {
            printf("\033[31merror: can't open file!\033[0m\n");
            exit(0);
        }
    
        while (!feof(fp))
        {
            token[c++] = fgetc(fp);
        }
        token[c] = '#';
        strncpy(p->token, token, sizeof(p->token));  
        // 绑定所有方法  
        p->isNumber = isNumber;
        p->i=0;
        p->line=0;
        p->row=0;
        p->is_f_j=0;
        p->is_z_y=0;
        p->pData=malloc(sizeof(char*));
        p->symbol = symbol;  
        p->letter = letter;  
        p->digit = digit;  
        p->reserve = reserve;  
        p->toLexAnalyze = toLexAnalyze;  
        p->getLexAnalyze=getLexAnalyze;
    }  
    return p; 
}